home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / cool / cool.lha / ice / papers / cool-exception-handling.ms < prev    next >
Text File  |  1991-09-04  |  37KB  |  713 lines

  1. .nr PS 10
  2. .nr VS 12
  3. .nr PD .7v
  4. .nr LL 6.5i
  5. .TL
  6. A Portable Exception Handling Mechanism for C++
  7. .AU
  8. Mary Fontana
  9. LaMott Oren
  10. .AI
  11. Texas Instruments Incorporated
  12. Computer Science Center
  13. Dallas, TX  75265
  14. fontana@csc.ti.com
  15. oren@csc.ti.com
  16. .AU
  17. Martin Neath
  18. .AI
  19. Texas Instruments Incorporated
  20. Information Technology Group
  21. Austin, TX  78714
  22. neath@itg.ti.com
  23. .AB
  24. The Texas Instruments C++ Object-Oriented Library (COOL) is a collection of
  25. classes, templates, and macros for use by C++ programmers who need to write
  26. complex yet portable applications.  The COOL exception handling mechanism is
  27. one component of this library that substantially improves the development and
  28. expressive capabilities available to programmers by allowing them to control
  29. the action to be taken by their programs when exceptional or unexpected
  30. situations occur.  This paper describes the facilities provided by COOL to
  31. raise, handle, and proceed from exceptions in a C++ class library or program
  32. and provides several examples of its use and flexibility. 
  33. .AE
  34. .NH 1
  35. Introduction
  36. .LP
  37. The Texas Instruments C++ Object-Oriented Library (COOL) is a collection of
  38. classes, templates, and macros for use by C++ programmers writing complex
  39. applications.  An important feature of this library is the ability to create
  40. and raise exceptions in the library for which a user of this class library can
  41. define his/her own exception handler routines to effectively and appropriately
  42. handle the exceptions in an application at runtime. This is especially
  43. important since current C++ compiler implementations do not contain an
  44. exception handling facility [6]. For an overview of the COOL class library, see
  45. the paper,
  46. .I
  47. COOL - A C++ Object-Oriented Library 
  48. .R
  49. [2].
  50. For complete details, see the reference document,
  51. .I
  52. COOL User's Guide 
  53. .R
  54. [8].
  55.  
  56. The COOL exception handling facility consists of a set of classes and macros to
  57. define, create, raise and handle exceptions. It is implemented with the COOL
  58. macro facility [3] and symbolic computing capability [4] and is similar to the
  59. Common Lisp Condition Handling system [1] in that both implement an exception
  60. system with the ability for resumption.  Briefly, when a program encounters a
  61. particular or unusual situation that is often (but not necessarily) an error,
  62. it can (1) represent the situation in an exception object, (2) announce that
  63. the situation has occurred by raising the exception, (3) provide ways to deal
  64. with the situation by defining and establishing handlers, and (4) continue or
  65. proceed from the situation after invoking a handler. One possible action for a
  66. handler is to correct some piece of erroneous information and retry the
  67. operation.
  68.  
  69. The COOL exception handling facility represents exceptions as objects derived
  70. from an exception class and provides a generic exception handler class, a set
  71. of predefined subclasses of the base exception class, and a set of default
  72. exception handler functions.  Several macros -- \fBEXCEPTION\fR, \fBRAISE\fR,
  73. \fBSTOP\fR, and \fBVERIFY\fR -- provide a simple interface to the exception
  74. handling facility and allow a programmer to easily create and raise exceptions.
  75. In addition, the macro \fBIGNORE_ERRORS\fR provides a convenient means by which
  76. a programmer can explicitly disable the exception handling system while
  77. executing a block of statements. Finally, the \fBDO_WITH_HANDLER\fR and
  78. \fBHANDLER_CASE\fR macros offer functionality similar to that described by
  79. Koenig and Stroustrup [5] to associate a block of statements with a provision
  80. for handling a specific set of possible exceptions.
  81.  
  82. Exception handlers are also represented as objects derived from an exception
  83. handler class. When an exception handler object is instantiated, it is placed
  84. at the top of a global exception handler stack. When an exception handler
  85. object is destroyed, the handler is removed from the exception handler stack.
  86. This stack is maintained in a similar way to that described by Miller [7]. When
  87. an exception is raised, a search is performed for an appropriate handler
  88. starting at the top of the exception handler stack. Since the most recently
  89. defined handler objects are placed at the top of the stack, localized or
  90. specialized handlers take precedence over more generic system-wide handlers.
  91. When a match against an exception type or group name is found, the exception
  92. handler object invokes the handler function.  An exception handler function
  93. might report the exception to the standard error stream and terminate the
  94. program, generate debug information by dumping a core image or stack trace to
  95. disk, or attempt to fix the problem and retry the operation again.
  96. .NH 1
  97. The Exception Class
  98. .LP
  99. Exceptions are represented as objects of an exception class and are used as a
  100. means of saving and communicating the state information representing a
  101. particular problem or condition to the appropriate exception handler.  When an
  102. exception can be corrected and resumption is possible, information on the new
  103. state is stored in the exception object by the invoked exception handler
  104. function and returned to the point at which the exception was raised.  The COOL
  105. \fBException\fR class is the base class from which specialized exception
  106. classes are derived. It contains data members to store a message string prefix,
  107. a format control string, a list of one or more group names or exception aliases
  108. for which this exception class is appropriate, and a flag to indicate whether
  109. or not an exception is handled.  User-derived exception classes can include
  110. additional data members for saving the incorrect values detected by a program.
  111. These values report the state to the exception handler and are often used by an
  112. exception handler when reporting the exception/error message to some
  113. interactive stream.
  114.  
  115. The \fBException\fR class has several generic member functions for use by all
  116. exception objects. The virtual member function \fBreport()\fR uses the message
  117. prefix and format string data members to report an exception message on a
  118. specified stream. The virtual member function \fBraise()\fR searches for an
  119. exception handler and invokes it if found.  The \fBmatch()\fR member function
  120. indicates if an exception object is included in one of the exception group
  121. names (aliases).  The output operator is overloaded for the \fBException\fR
  122. class to call the \fBreport()\fR member function. Member functions to query
  123. whether or not an exception has been handled and to set the handled flag are
  124. also available. Finally, the virtual \fBdefault_handler()\fR member function is
  125. invoked if no exception handler is found.
  126.  
  127. As mentioned above, data members can be included in a derived exception class
  128. as a way for the signaller (the one who raises the exception) to indicate to an
  129. exception handler ways of proceeding from the exception.  For example, if an
  130. exception occurs because a variable has an incorrect value, an exception object
  131. of the appropriate type is created and then the exception is raised.  The
  132. exception object defined for this situation would have a data member with the
  133. incorrect value and a data member for the new value.  An exception handler
  134. could be established to handle this type of situation by supplying a new value
  135. (possibly by interactively informing the user about the incorrect value and
  136. querying for a new value through an appropriate interface), store this new
  137. value in the exception object, and return the exception object to the
  138. signaller.  The signaller would then assign this new value to the variable in
  139. error and execution at the point the exception was raised would resume.
  140. .NH 1
  141. Exception Handler Class
  142. .LP
  143. When an exception handler is invoked after a successful search of the global
  144. exception handler stack, it's handler function is called with the raised
  145. exception object as an argument.  The handler function may correct the problem,
  146. ignore it, or do most anything else appropriate. For the case in which an
  147. attempt is made to fix the problem and resumption is possible, the point in the
  148. program or library at which the exception is raised can contain statements to
  149. determine the new or changed values and state information, update any local
  150. variables accordingly, and resume execution. All the information and processing
  151. associated with exception handling is represented by an instance of an
  152. exception handler class.
  153.  
  154. The \fBExcp_Handler\fR class has two data members. The first is a list of one
  155. or more exception types or group names (aliases) and the second is a pointer to
  156. a function to be called to handle a raised exception that matches against a
  157. value in the exception type list. These data members are initialized by the
  158. argument list of the constructor and cannot be changed once set. The
  159. \fBExcp_Handler\fR class has a single virtual member function
  160. \fBinvoke_handler()\fR that takes a single argument -- a pointer to the
  161. exception object -- and invokes the exception handler function. This function
  162. may or may not return, depending upon whether the handler attempts to resume
  163. execution or terminate the operation.
  164. .NH 1
  165. Exception Group Names (Aliases)
  166. .LP
  167. As with most exception handling systems, the COOL exception facility supports
  168. the grouping of exceptions by the class hierarchy. However, as mentioned
  169. above, the COOL exception handling facility also supports the concept of
  170. exception group names or aliases.  Grouping of exception names is implemented
  171. through the alias/group name data member in each exception object.  These group
  172. names allow a programmer to raise a single exception but associate that
  173. exception with several names or aliases rather than with just one. This means
  174. that a single exception class might be handled by one of several different
  175. exception handlers appropriate under different situations. The net result for
  176. the programmer is that only one exception class needs to be defined instead of
  177. several very similar classes. The group names are implemented using the COOL
  178. symbolic computing facility [4] for efficiency, but could be implemented using
  179. simple character strings to represent each name.
  180.  
  181. For example, suppose a programmer is implementing a parameterized Vector<Type>
  182. class in a generic class library to be used by several other programmers in the
  183. company. Some of these other programmers want to have a detailed set of options
  184. for dealing with exceptions, including resumption, while others want only a
  185. simple fail-safe termination mechanism. The Vector class programmer wishes to
  186. provide exception handling in the overloaded Vector<Type>::operator[] member
  187. function that satisfies all potential users of the class. To accomplish this, a
  188. single exception class \fBOut_Of_Bounds\fR is derived from the base class
  189. \fBException\fR with appropriate data members added to contain the old index
  190. value and a possible new value. If an index out of bounds error is detected, an
  191. exception object is created with one type name provided by the class hierarchy
  192. mechanism -- \fBOut_Of_Bounds\fR -- and two group names -- \fBVector_Error\fR
  193. and \fBFatal_If_Not_Handled\fR -- representing different exception reporting
  194. granularity.  These three names for one exception type allow three different
  195. users of this class to achieve varying levels of sophistication in their
  196. exception handlers while requiring the class programmer to only implement one
  197. exception class for the parameterized vector class. If an Out_Of_Bounds
  198. exception is raised, the first exception handler found on the global exception
  199. handler stack that can handle either the exception type or one of the three
  200. exception group names supported will be invoked.
  201. .NH 1
  202. Predefined Exception Types and Handlers
  203. .LP
  204. COOL provides seven predefined exception class and five default exception
  205. handlers.  The \fBException\fR class is the base exception class from which all
  206. other exception classes are derived. The \fBWarning\fR, \fBFatal\fR,
  207. \fBError\fR, and \fBSystem_Signal\fR classes are immediately derived from the
  208. base class. The \fBSystem_Error\fR and \fBVerify_Error\fR classes are derived
  209. from the \fBError\fR class. Each of these predefined exception types has a
  210. default report member function and a default exception handler member function
  211. that is only invoked if no other exception handler is
  212. established by the programmer and found on the global exception handler stack
  213. when an exception is raised.
  214.  
  215. For exceptions of type \fBError\fR and \fBFatal\fR, the default exception
  216. handler reports the error message on the standard error stream and terminates
  217. the program with \fBexit()\fR or writes a core image and/or stack trace out to
  218. disk with \fBabort()\fR. If the exception is of type \fBWarning\fR, the warning
  219. message is reported on the standard error stream and the program resumes at the
  220. point at which the exception was raised.  If the exception is of type
  221. \fBSystem_Error\fR, the system error message is reported on the standard error
  222. stream and the program is terminated.  If the exception is of type
  223. \fBSystem_Signal\fR, the signal is reported and the program resumes execution
  224. after the call of the system function \fBsignal(2)\fR. In all cases, the default
  225. exception handler is merely a place-holder to insure that there is at least one
  226. handler for each type of exception available at all times on the global
  227. exception handler stack. Users are expected to provide their own 
  228. exception handler classes that handle particular exception group names used
  229. within the COOL class library in a more appropriate application-specific manner.
  230. .NH 1
  231. Exception Handling Macros
  232. .LP
  233. The COOL exception handling facility uses the COOL macro facility [3] to create
  234. macros for creating, raising, and manipulating exceptions.  The \fBEXCEPTION\fR
  235. macro simplifies the process of creating an instance of a particular type of
  236. exception object. The \fBRAISE\fR macro allows the programmer to easily
  237. construct and raise an exception, then perform a search for an appropriate
  238. exception handler and invoke the handler function.  The \fBSTOP\fR macro is
  239. similar to \fBRAISE\fR, except that it guarantees to end the program if the
  240. exception is not handled. The \fBVERIFY\fR macro raises an exception if an
  241. assertion for some specified expression evaluates to zero. The
  242. \fBIGNORE_ERRORS\fR macro is a wrapper that can be placed around a body of
  243. statements to ignore exceptions raised while executing that body.  The
  244. \fBDO_WITH_HANDLER\fR macro establish an exception handler effective for the
  245. duration of a block. Finally, the \fBHANDLER_CASE\fR macro establishes an
  246. exception handler that transfers control to a series of exception-case clauses
  247. similar to the \fBtry\fR/\fBcatch\fR concept proposed by Koenig/Stroustrup [5].
  248. .NH 2
  249. The EXCEPTION Macro
  250. .LP
  251. The \fBEXCEPTION\fR macro simplifies the process of creating an instance of a
  252. particular type of exception object. It provides an interface for the
  253. application programmer to create an exception object using the specified
  254. arguments to indicate one or more group names, initialize any data members, or
  255. generate a format message. \fBEXCEPTION\fR is implemented as a COOL macro and
  256. has the following syntax:
  257. .DS I
  258. \fBEXCEPTION (\fIexcp_name\fB [, \fIgroup_names\fR] [, \fIformat_string\fR] [, \fIargs\fB])\fR
  259. .DE
  260. where \fIexcp_name\fR is the COOL symbol representing the exception class type
  261. (such as, \fBError\fR or \fBWarning\fR), \fIgroup_names\fR are one or more
  262. pointers to COOL symbols each of which represents a group or alias name for
  263. this exception, \fIformat_string\fR is a \fBprintf(2)\fR compatible control
  264. string, and \fIargs\fR are any combination of format arguments and keyword 
  265. arguments to initialize data members. For example, the following macro 
  266. invocation might be used to implement the index-bounds exception for the 
  267. Vector<Type> class discussed above:
  268. .DS I
  269. EXCEPTION (Out_Of_Bounds, SYM(Vector_Error), SYM(Fatal_If_Not_Handled)), 
  270.               "Index %d out of bounds for vector of type %s", bad_index = i, #Type);
  271. .DE
  272. The first argument is the exception type (ie. a new exception class derived
  273. from \fBException\fR), the second and third arguments are entries in the COOL
  274. symbol table for two group names (aliases) to be associated with this exception
  275. object, the third argument is a message string, and the last two arguments
  276. provide values for the fields in the message.
  277. The fourth argument also initializes a data member.  When expanded, this macro
  278. generates:
  279. .DS I
  280. (Exception_g = new Out_Of_Bounds(), 
  281.  Exception_g = set_group_names(2, SYM(Vector_Error), SYM(Fatal_If_Not_Handled)),
  282.  Exception_g->format_msg = ERR_MSG (hprintf ("Index %d out of bounds for vector of type %s",
  283.                                                                i, #Type)),
  284.  ((Out_Of_Bounds*)Exception_g)->bad_index = i,
  285.  Exception_g);
  286. .DE
  287. This comma-separated expression creates a new \fBOut_Of_Bounds\fR exception
  288. object on the heap and assigns it to the pointer \fBException_g\fR. The two
  289. group names are added as symbols using the \fBset_group_names()\fR member
  290. function. The format message is created by \fBhprintf()\fR, which is a
  291. variation of \fBprintf(2)\fR that returns a formated string allocated on the
  292. heap.  This string is placed in the COOL \fBERR_MSG\fR table that facilitates
  293. simple internationalization of text strings in an application [4].
  294. Finally, the data member \fBbad_index\fR is initializied with the value \fBi\fR.
  295. .NH 2
  296. The RAISE Macro
  297. .LP
  298. The \fBRAISE\fR macro simplifies the process of creating and raising an
  299. exception. The exception object is constructed using \fBEXCEPTION\fR and is
  300. raised using the member function \fBraise()\fR.  If one is found of the
  301. appropriate type, it's handler function is invoked and passed the exception
  302. object as an argument. \fBRAISE\fR returns the exception object if the
  303. exception handler function returns or if no exception handler is found.
  304. \fBRAISE\fR is implemented as a COOL macro and has the following syntax:
  305. .DS I
  306. \fBRAISE (\fIexcp_name\fB [, \fIgroup_names\fR] [, \fIformat_string\fR] [, \fIargs\fB])\fR
  307. .DE
  308. where \fIexcp_name\fR is the COOL symbol representing the exception class type
  309. (such as, \fBError\fR or \fBWarning\fR), \fIgroup_names\fR are one or more
  310. pointers to COOL symbols each of which represents a group or alias name for
  311. this exception, \fIformat_string\fR is a \fBprintf(2)\fR compatible control
  312. string, and \fIargs\fR are any combination of format arguments and keyword 
  313. arguments to initialize data members. 
  314.  
  315. The \fBRAISE\fR macro is used extensively in COOL and is often the most
  316. convenient form used by programmers. The following example continues with the
  317. index-bounds exception for the Vector<Type> class from above.  Suppose an
  318. application programmer is working on a tutorial programming environment that
  319. provides assistance at runtime to novice programmers.  The programmer wishes to
  320. set up an exception handler to handle the index-bounds error by prompting for a
  321. new value, storing the result in the exception object, and retrying the
  322. operation.  The class programmer implementing the Vector<Type> could write
  323. the code for the member function Vector<Type>::operator[] in the class library
  324. and raise an exception and process it as follows:
  325. .DS I
  326. class Out_Of_Bounds : public Error {
  327. public:
  328.     unsigned int bad_index;
  329.     unsigned int new_index;
  330.     char* container;
  331.     char* type;
  332.     Out_of_Bounds() { format_msg = "Index %d out of bounds for %s of type %s"; }
  333.     virtual void report (ostream& os) { os << msg_prefix << form(format_msg, bad_index, container, type);}
  334. };
  335.  
  336. int Vector<Type>::operator[] (int i) {
  337.     while(TRUE) {
  338.         if (i >= 0 && i < this->number_elements)
  339.             return this->data[i];
  340.         else {
  341.             Error* e = RAISE (Out_of_Bounds, bad_index = i, container = "Vector", type = #Type);
  342.             if (e->exception_handled())
  343.                 i = e->new_index;
  344.         }
  345.     }
  346. }
  347. .DE
  348. The application programmer writing the programming environment defines an
  349. exception handler function to prompt for a new index and an instance of a
  350. handler object to associate with the function for the \fBOut_Of_Bounds\fR
  351. exception in the following manner:
  352. .DS I
  353. void Bounds_Index_Handler (Exception& excp) {
  354.     excp.report(cout);
  355.     cout << "New index to use instead: " << flush;
  356.     cin >> excp.new_index;
  357.     excp.handled(TRUE);
  358. }
  359.  
  360. Excp_Handler vec_eh (Bounds_Index_Handler, SYM(Out_Of_Bounds));
  361. .DE
  362. The exception handler object \fBvec_eh\fR should be declared at what ever
  363. scope is necessary for exceptions of this type to be handled in this manner.
  364. This is usually, but not always, declared as a global instance so as to insure
  365. that the handler is available at all times during the run of an application.
  366. When the user of this system runs the program with an erroneous index, the
  367. \fBOut_Of_Bounds\fR exception is raised in the class library, the exception
  368. handler \fBBounds_Index_Handler\fR written by the application programmer is
  369. invoked and prompts for a new index, then the operation retryed. Note that the
  370. three programmer's involved in this system (the class programmer, the
  371. application programmer, and the novice programmer) had no interaction with each
  372. other and no discussion over the design and interface to the exception handling
  373. facility.  However, the class programmer was able to use a flexible exception
  374. handling system that was customized with an application-specific handler to
  375. afford a more helpful system for the novice programmer. Finally, note that in
  376. this example, proceeding from the raised exception involves no use of the
  377. system setjmp/longjmp functions.
  378. .NH 2
  379. The STOP Macro
  380. .LP
  381. The \fBSTOP\fR macro creates and raises an exception similar to the \fBRAISE\fR
  382. macro except that it guarantees to terminate program execution if an exception
  383. handler returns (ie. attempts to resume) or if no exception handler is found.
  384. The exception object is constructed in the same manner using the
  385. \fBEXCEPTION\fR macro and raised using the member function \fBstop()\fR.
  386. \fBSTOP\fR is implemented as a COOL macro and has the following syntax:
  387. .DS I
  388. \fBSTOP (\fIexcp_name\fB [, \fIgroup_names\fR] [, \fIformat_string\fR] [, \fIargs\fB])\fR
  389. .DE
  390. where \fIexcp_name\fR is the COOL symbol representing the exception class type
  391. (such as, \fBError\fR or \fBWarning\fR), \fIgroup_names\fR are one or more
  392. pointers to COOL symbols each of which represents a group or alias name for
  393. this exception, \fIformat_string\fR is a \fBprintf(2)\fR compatible control
  394. string, and \fIargs\fR are any combination of format arguments and keyword 
  395. arguments to initialize data members.
  396. .NH 2
  397. The VERIFY Macro
  398. .LP
  399. The \fBVERIFY\fR macro asserts that an expression has a non-zero value by
  400. raising an exception of the specified type if the expression evaluates to zero.
  401. The exception object is constructed with \fBEXCEPTION\fR and is raised using
  402. the member function \fBraise()\fR.  The exception type is optional and, 
  403. if not given, defaults to \fBVerify_Error\fR. This exception class is derived
  404. from \fBError\fR and contains a data member for storing a string representation
  405. of the expression that failed. \fBVERIFY\fR is implemented as a COOL macro and
  406. has the following syntax:
  407. .DS I
  408. \fBVERIFY (\fItest_expression\fB, \fIexcp_name\fB = Verify_Error\fR [, \fIgroup_names\fR] [, \fIformat_string\fR] [, \fIargs\fB])\fR
  409. .DE
  410. where \fItest_expression\fR is the C++ expression to be verified,
  411. \fIexcp_name\fR is the optional argument specifying the exception type,
  412. \fIgroup_names\fR are one or more pointers to COOL symbols each of which
  413. represents a group or alias name for this exception, \fIformat_string\fR is a
  414. \fBprintf(2)\fR compatible control string, and \fIargs\fR are any combination
  415. of format arguments and keyword arguments to initialize data members.
  416. For example, the
  417. following macro invocation might be used to implement an alternate approach
  418. for the index-bounds exception discussed above:
  419. .DS I
  420. int Vector<Type>::operator[] (int i) {
  421.     VERIFY ((i >= 0 && i < this->number_elements));
  422.     return this->data[i];
  423. }
  424. .DE
  425. Since only the expression to assert is passed as an argument, the \fBVERIFY\fR
  426. macro creates a \fBVerify_Error\fR exception object by default and initializes
  427. the inherited data members. When expanded, this macro generates:
  428. .DS I
  429. if (!(i >= 0 && i < this->number_elements)) 
  430.     (Exception_g = new Verify_Error(), 
  431.     Exception_g)->raise();
  432. .DE
  433. .NH 2
  434. The IGNORE_ERRORS Macro
  435. .LP
  436. The \fBIGNORE_ERRORS\fR macro ignores an exception that is raised while
  437. executing a body of statements. If an exception of a specified type or types is
  438. raised while within the scope of this body, the macro insures that the handler
  439. for that exception is not invoked, but rather, control is returned to the point
  440. immediately following the body. \fBIGNORE_ERRORS\fR is implemented as a COOL
  441. macro and has the following syntax:
  442. .DS I
  443. \fBIGNORE_ERRORS (\fIexcp_ptr\fR [, \fIexcp_class\fB = Error\fR] [, \fIgroup_names\fR]) { \fIbody\fB }\fR
  444. .DE
  445. If an exception of type \fIexcp_class\fR (or with group \fIgroup_names\fR) is
  446. raised while executing \fIbody\fR, then \fIexcp_ptr\fR is set to the address of
  447. this exception object and program control transfers to the statement following
  448. \fBIGNORE_ERRORS\fR.  If no exception is raised while executing \fIbody\fR,
  449. then \fIexcp_ptr\fR is set to \fBNULL\fR.  The exception must have been raised
  450. with the \fBRAISE\fR, \fBSTOP\fR, or \fBVERIFY\fR macros.
  451. If \fIexcp_class\fR is not specified, the
  452. default exception class is \fBError\fR.  \fBIGNORE_ERRORS\fR is implemented
  453. using the system functions, setjmp and longjmp. As a result, the statements
  454. within the braces should not require destructors to be invoked because the
  455. setjmp/longjmp mechanism does not currently support this capability.
  456.  
  457. In the following program fragment, \fBIGNORE_ERRORS\fR is used to ignore an
  458. exception of type \fBError\fR raised while using operator[] of the Vector<Type>
  459. class. In this case, the exception object is send to the standard error
  460. stream and execution continues.  If \fBIGNORE_ERRORS\fR were not used
  461. and no other exception handler had been defined, the default exception handler
  462. for \fBError\fR would terminate the program with a call to \fBexit(2)\fR.
  463. .DS I
  464. Vector<int> data[4];
  465. Error* e;
  466. IGNORE_ERRORS (e) {
  467.     int i;
  468.     i = data[5];
  469. }
  470. if (e != NULL) 
  471.     cerr << e;
  472. .DE
  473. .NH2
  474. The DO_WITH_HANDLER Macro
  475. .LP
  476. The \fBDO_WITH_HANDLER\fR macro establishes an exception handler whose scope is
  477. restricted to a specified body of statements.  An exception handler that
  478. matches against one of the exception types or group names in the exception list
  479. is established during execution of a series of statements. The specified
  480. exception handler will be invoked if an exception of the specified type or
  481. group is raised and no other more-recently-established handler matches the type
  482. or group names. The exception must have been raised with the \fBRAISE\fR, 
  483. \fBSTOP\fR, or \fBVERIFY\fR macros.
  484. \fBDO_WITH_HANDLER\fR is implemented as a COOL macro and has
  485. the following syntax:
  486. .DS I
  487. \fBDO_WITH_HANDLER (\fIexh_func\fR [, \fIexcp_types\fR]) { \fIbody\fB }\fR
  488. .DE
  489. where \fIexh_func\fR is the name of an exception handler function,
  490. \fIexcp_types\fR is a list of one or more exception types and group names, and
  491. \fIbody\fR specifies one or more C++ statements surrounded by braces. In the
  492. following example, a specialized exception handler for the index-bounds problem
  493. in the Vector<Type>::operator[] class is established for a small body of code:
  494. .DS I
  495. extern void New_Out_Of_Bounds_Handler(Exception&);
  496. Vector<int> data[4];
  497. DO_WITH_HANDLER (New_Out_Of_Bounds_Handler, SYM(Out_Of_Bounds)) {
  498.     int sum;
  499.     for(int i = 0; i <= data.length(); i++)
  500.         sum += data[i];
  501. }    
  502. .DE
  503. This code fragment contains a typical indexing problem where the programmer
  504. has an inaccurate loop-termination test, thus incrementing the index one too
  505. many times and causing an exception to be raised. When expanded, this macro
  506. generates:
  507. .DS I
  508. extern void New_Out_Of_Bounds_Handler(Exception&);
  509. Vector<int> data[4];
  510. {
  511.     Excp_Handler _do_eh(New_Out_Of_Bounds_Handler, SYM(Out_Of_Bounds));
  512.     int sum;
  513.     for(int i = 0; i <= data.length(); i++)
  514.     sum += data[i];
  515. }
  516. .DE
  517. .NH2
  518. The HANDLER_CASE Macro
  519. .LP
  520. The \fBHANDLER_CASE\fR macro establishes an exception handler that transfers
  521. control to a set of exception-case clauses when an exception is raised while
  522. executing a body of statements. \fBHANDLER_CASE\fR is implemented as a COOL
  523. macro and has the following syntax:
  524. .DS I
  525. \fBHANDLER_CASE { \fIbody\fB }\fR { \fIcase_clauses\fR }
  526. \fIcase_clauses\fR ::= \fBcase\fR ([\fIexcp_spec\fR]) \fB:\fR {\fIstatements\fR} [\fIcase_clauses\fR]
  527. \fIexcp_spec\fR ::= [\fIexcp_types\fR] [,\fI excp_class excp_decl\fR]
  528. \fIexcp_types\fR ::= \fIexcp_class_or_group_type\fR [, \fIexcp_types\fR]
  529. .DE
  530. If an exception is raised while executing \fIbody\fR, an exception handler will
  531. be invoked to transfer control to \fIcase_clauses\fR.  The statements of the
  532. \fIcase_clause\fR whose \fIexcp_spec\fR matches the raised exception type or
  533. one of its group names is executed. The variable \fIexcp_decl\fR is bound to
  534. the \fIexcp_class\fR exception object raised and may be referenced by any
  535. statement in the matching \fIcase_clause\fR. The exception must have been
  536. raised with \fBRAISE\fR, \fBSTOP\fR, or \fBVERIFY\fR.
  537. Finally, as in \fBIGNORE_ERRORS\fR, the
  538. \fBHANDLER_CASE\fR macro is implemented using the system functions, setjmp and
  539. longjmp. As a result, the statements within the matching \fIcase_clause\fR
  540. should not require destructors to be invoked because the setjmp/longjmp
  541. mechanism does not currently support this capability.  The following example
  542. shows the use of this macro with the index-bounds problem used throughout this
  543. paper:
  544. .DS I 
  545. Boolean calculate_sum (Vector<int>& v1, int start, int end)
  546. {
  547.     HANDLER_CASE {
  548.         int sum;
  549.         for(int i = start; i <= end; i++)
  550.             sum += v1[i];
  551.         }
  552.     v1.push(sum);
  553.     }
  554.     case (SYM (Out_Of_Bounds), Error eh) : {
  555.         cerr << eh; 
  556.         return FALSE;
  557.     }
  558.     case (SYM (Resize_Error), SYM (Static_Error), Error eh) : {
  559.         cerr << eh; 
  560.         abort();
  561.     }
  562.     case (Error eh) : {
  563.         cerr << eh; 
  564.         exit();
  565.     }
  566.     return TRUE;
  567. }  
  568. .DE
  569. This function takes a reference to a vector object, a starting index, and an
  570. ending index to compute the sum of the elements between and including these
  571. indexes. If an exception occurs during this operation, control is transferred
  572. to the appropriate case statement clause. If an exception of type
  573. \fBOut_Of_Bounds\fR is raised, the exception object is printed on the standard
  574. error stream and the value FALSE is returned from the function. If the raised
  575. exception has a group name of either \fBResize_Error\fR or \fBStatic_Error\fR,
  576. the exception object is printed on the standard error stream and the program
  577. aborts.  Finally, as a default condition, if any other type of exception is
  578. raised, the exception object is printed on the standard error stream and the
  579. program exits. If no exceptions are raised, the sum of the elements is pushed
  580. onto the end of the vector object and the value TRUE is returned from the
  581. function.
  582. .NH 1
  583. COOL Exception Handling Comparison to Koenig/Stroustrup Proposal
  584. .LP
  585. The COOL exception handling facility implements a portable, compiler
  586. independent, object-oriented exception handling capability. Exceptions are
  587. classified according to subtype relationships making it easy to test for a
  588. group of exceptions. These exception objects have data members through which
  589. state information is conveyed from the point at which the exception is raised
  590. to the handler. The base exception and handler classes contain generic virtual
  591. functions upon which more sophisticated capabilities can be built through
  592. inheritance and derivation.
  593.  
  594. The COOL exception handling macros, \fBRAISE\fR and \fBHANDLER_CASE\fR, provide
  595. the same type of functionality as the \fBthrow\fR and \fBtry-catch\fR
  596. statements proposed by Koenig and Stroustrup in their paper,
  597. .I
  598. Exception Handling for C++ 
  599. .R
  600. [5]. Both \fBthrow\fR and \fBRAISE\fR transfer control to the most recently
  601. establish handler for a particular type of exception. However, any object may
  602. be used as an argument in a \fBthrow\fR expression, whereas \fBRAISE\fR only
  603. passes exception objects. In a similar manner, the \fBtry-catch\fR block and
  604. the \fBHANDLER_CASE\fR macro establish some handlers while executing a body of
  605. statements. The difference here is that the \fBcatch\fR expression in a
  606. \fBtry\fR block is like a function definition and any data type can be
  607. specified in the exception declaration. The case statements in the
  608. \fBHANDLER_CASE\fR macro, on the other hand, accept only COOL symbol objects.
  609. These symbols allow for group names and aliases to be used to handle a single
  610. kind of exception in one of several ways.
  611.  
  612. These differences are minor, however, when compared to the philosophical models
  613. each system follows: termination versus resumption. In the one, the \fBthrow\fR
  614. unwinds the stack before the call of the exception handler, thus supporting a
  615. termination model for exception handling, while in the second, the \fBRAISE\fR
  616. macro expands into a function call before the stack is unwound, thus supporting
  617. a resumption model for exception handling.
  618. .NH 1
  619. Conclusion
  620. .LP
  621. The COOL exception handling facility is a set of classes and macros that
  622. provide a mechanism to detect and raise an exception and independently
  623. establish and invoke an exception handler to deal with the exception in another
  624. part of the application. An exception handler may either fix the problem and
  625. resume execution, retry the operation, or terminate the program.  The virtual
  626. member functions \fBreport\fR, \fBraise\fR, \fBdefault_handler\fR, and
  627. \fBmatch\fR can be customized in user-defined exception classes derived from
  628. the base \fBException\fR and \fBExcp_Handler\fR classes.  The macros
  629. \fBEXCEPTION\fR, \fBRAISE\fR, \fBSTOP\fR, \fBVERIFY\fR, \fBIGNORE_ERRORS\fR,
  630. \fBDO_WITH_HANDLER\fR, and \fBHANDLER_CASE\fR provide a consistent and
  631. convenient way for the programmer to create, raise, and handle exceptions.
  632.  
  633. There are still a number of problems that need to be addressed in the COOL
  634. exception handling system.  Of particular concern are how to handle exceptions
  635. raised in constructors and destructors, and the destruction of objects when
  636. setjmp/longjmp are used. Texas Instruments has been using the exception
  637. handling facility internally on several projects in conjunction with the COOL
  638. class library. We have found that the use of a flexible exception handling
  639. system enables programmer's to customize the error handling to suit a specific
  640. application. As a result, class libraries are more useful and reusable, thus
  641. significantly increasing the productivity of the programmer and thus enabling
  642. applications to be prototyped in a shorter time period than might otherwise be
  643. possible.  COOL is currently up and running on a Sun SPARCstation 1 (TM)
  644. running SunOS (TM) 4.x,
  645. .FS
  646. SunOS and SPARCstation 1 are trademarks of Sun Microsystems, Inc.
  647. .FE
  648. a PS/2 (TM) 
  649. .FS
  650. PS/2 is a trademark of International Business Machines Corporation.
  651. .FE
  652. model 70 running SCO XENIX\(rg
  653. .FS
  654. XENIX is a registered trademark of Microsoft Corporation.
  655. .FE
  656. 2.3, a PS/2 model 70 running OS/2 1.1, and
  657. a MIPS running RISC/os 4.0. The SPARC and MIPS ports utilize the AT&T C++
  658. translator (cfront) version 2.0 and the XENIX and OS/2 ports utilize the
  659. Glockenspiel translator with the Microsoft C compiler.
  660. .NH 1
  661. References
  662. .IP [1]
  663. Andy Daniels and Kent Pitman,
  664. .I
  665. Common Lisp Condition System Revision #18,
  666. .R
  667. ANSI X3J13 subcommittee on Error Handling, March 1988.
  668. .IP [2]
  669. Mary Fontana, Martin Neath and Lamott Oren,
  670. .I
  671. COOL - A C++ Object-Oriented Library,
  672. .R
  673. Information Technology Group, Austin, TX, Internal Original Issue January 1990.
  674. .IP [3]
  675. Mary Fontana, Martin Neath and Lamott Oren,
  676. .I
  677. A Portable Implementation of Parameterized Templates Using A Sophisticated C++
  678. Macro Facility, 
  679. .R
  680. Information Technology Group, Austin, TX, Internal Original Issue January 1990.
  681. .IP [4]
  682. Mary Fontana, Martin Neath and Lamott Oren,
  683. .I
  684. Symbolic Computing for C++,
  685. .R
  686. Information Technology Group, Austin, TX, Internal Original Issue January 1990.
  687. .IP [5]
  688. Andrew Koenig and Bjarne Stroustrup,
  689. .I
  690. Exception Handling for C++,
  691. .R
  692. Submitted as document X3J16/90-042 to the ANSI C++ committee, July, 1990.
  693. .IP [6]
  694. Stanley Lippman,
  695. .I
  696. C++ Primer,
  697. .R
  698. Addison-Wesley, Reading, MA, 1989.
  699. .IP [7]
  700. Mike Miller,
  701. .I
  702. Exception Handling Without Language Extensions,
  703. .R
  704. Proceedings of the USENIX C++ Conference, Denver, CO, October 17-21, 1988,
  705. pp. 327-341.
  706. .IP [8]
  707. Texas Instruments Incorporated,
  708. .I
  709. COOL User's Guide,
  710. .R
  711. Information Technology Group, Austin, TX, Internal Original Issue January 1990.
  712.  
  713.